#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "freertos/semphr.h"
#include "esp_system.h"
#include "esp_timer.h"
#include "esp_log.h"

#include "lvgl.h"
#include "lvgl_helpers.h"
#include "demos/lv_demos.h"

/*********************
 *      DEFINES
 *********************/
#define LV_TICK_PERIOD_MS 1

static void guiTask(void *pvParameter);
static void create_demo_application(void);
static void lv_tick_task(void *args);
static void event_handler(lv_event_t * e);

static void btnTask(void);

lv_obj_t * btn1;
lv_obj_t * btn2;

void app_main(void)
{
    xTaskCreatePinnedToCore(guiTask, "guiTask", 4096*2, NULL, 0, NULL,tskNO_AFFINITY);
    xTaskCreatePinnedToCore(btnTask, "btnTask",1024,NULL, 0, NULL,tskNO_AFFINITY);
}

SemaphoreHandle_t xGuiSemaphore;
SemaphoreHandle_t btnSemaphore;
static lv_disp_t *lv_disp_handle;
static void guiTask(void *pvParameter)
{
    xGuiSemaphore = xSemaphoreCreateMutex();
    //初始化lvgl
    lv_init();
    //初始化lvgl驱动
    lvgl_driver_init();

    //创建显示缓存
    lv_color_t *buf1 = heap_caps_malloc(DISP_BUF_SIZE * sizeof(lv_color_t), MALLOC_CAP_DMA);
    assert(buf1 != NULL);
    lv_color_t *buf2 = heap_caps_malloc(DISP_BUF_SIZE * sizeof(lv_color_t), MALLOC_CAP_DMA);
    assert(buf2 != NULL);
    static lv_disp_draw_buf_t disp_buf;
    uint32_t size_in_px = DISP_BUF_SIZE;
    lv_disp_draw_buf_init(&disp_buf, buf1, buf2, size_in_px);

    //初始化显示驱动
    lv_disp_drv_t disp_drv;
    lv_disp_drv_init(&disp_drv);
    disp_drv.hor_res = LV_HOR_RES_MAX;
    disp_drv.ver_res = LV_VER_RES_MAX;
    disp_drv.flush_cb = disp_driver_flush;
    disp_drv.draw_buf = &disp_buf;
    lv_disp_handle = lv_disp_drv_register(&disp_drv);

    const esp_timer_create_args_t timer_args = {
        .callback = lv_tick_task,
        .name = "lvgl tick timer"
    };
    esp_timer_handle_t esp_timer;
    ESP_ERROR_CHECK(esp_timer_create(&timer_args, &esp_timer));
    ESP_ERROR_CHECK(esp_timer_start_periodic(esp_timer, LV_TICK_PERIOD_MS * 1000));



    create_demo_application();
    
    while(1)
    {
        vTaskDelay(pdMS_TO_TICKS(10));

        if(pdTRUE == xSemaphoreTake(xGuiSemaphore, portMAX_DELAY))
        {
            lv_task_handler();
            xSemaphoreGive(xGuiSemaphore);
        }
    }

}
static void create_demo_application(void)
{
    lv_obj_t * label;

    btn1 = lv_btn_create(lv_scr_act());
    lv_obj_add_event_cb(btn1, event_handler, LV_EVENT_ALL, NULL);
    lv_obj_add_flag(btn1, LV_OBJ_FLAG_CHECKABLE);
    lv_obj_align(btn1, LV_ALIGN_CENTER, 0, -40);
    

    label = lv_label_create(btn1);
    lv_label_set_text(label, "Button");
    lv_obj_center(label);

    btn2 = lv_btn_create(lv_scr_act());
    lv_obj_add_event_cb(btn2, event_handler, LV_EVENT_ALL, NULL);
    lv_obj_align(btn2, LV_ALIGN_CENTER, 0, 40);
    lv_obj_add_flag(btn2, LV_OBJ_FLAG_CHECKABLE);
    lv_obj_set_height(btn2, LV_SIZE_CONTENT);
    
    label = lv_label_create(btn2);
    lv_label_set_text(label, "Toggle");
    lv_obj_center(label);
}
static bool colorFlag = false;
static void event_handler(lv_event_t * e)
{
    lv_event_code_t code = lv_event_get_code(e);

    if(code == LV_EVENT_CLICKED) {
        // if (pdTRUE == xSemaphoreTake(btnSemaphore, portMAX_DELAY))
        // {
            
        //     xSemaphoreGive(btnSemaphore);
        // }
        
        
    }
    else if(code == LV_EVENT_VALUE_CHANGED) {
        LV_LOG_USER("Toggled");
    }
}

static void lv_tick_task(void *args)
{
    lv_tick_inc(LV_TICK_PERIOD_MS);
}

static void btnTask(void)
{
    int n = 5;
    btnSemaphore = xSemaphoreCreateMutex();
    while(1)
    {
        vTaskDelay(pdMS_TO_TICKS(10));
        if (pdTRUE == xSemaphoreTake(btnSemaphore,portMAX_DELAY))
        {
            lv_event_send(btn1, LV_EVENT_CLICKED, NULL);
            lv_event_send(btn2, LV_EVENT_CLICKED, NULL);
            vTaskDelay(pdMS_TO_TICKS(500));
            lv_event_send(btn1, LV_EVENT_RELEASED, NULL);
            lv_event_send(btn2, LV_EVENT_RELEASED, NULL);
            xSemaphoreGive(btnSemaphore);
            vTaskDelay(pdMS_TO_TICKS(700));
            n--;
            
        }
        if(pdTRUE == xSemaphoreTake(xGuiSemaphore, portMAX_DELAY))
        {
            if (n == 0)
            {
                lv_refr_now(lv_disp_handle);
                n =5;
            }
            xSemaphoreGive(xGuiSemaphore);
        }
        
    }
}